package logic;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;

/**
 * class for low level interaction with bluetooth stream
 * @author Rekin
 *
 */
public class BluetoothConnection {
	private StreamConnection streamConnection;
	private InputStream inputStream;
	private OutputStream outputStream;
	
	private String localName;
	private String remoteName;
	private String url;
	
	/**
	 * constructor of connection from a given string url
	 * @param connectionUrl url with information about conneciton
	 * @param localName local device name
	 * @param remoteName remote device name
	 * @throws IOException
	 */
	public BluetoothConnection(String connectionUrl, String localName, String remoteName) throws IOException{
		this.localName = localName;
		this.remoteName = remoteName;
		this.url = connectionUrl;
		connect();
	}
	
	/**
	 * constructor of connection from a given stream connection
	 * @param con stream connection used to create bluetooth connection
	 * @param localName local device name
	 * @param remoteName remote device name
	 * @throws IOException
	 */
	public BluetoothConnection(StreamConnection con, String localName, String remoteName) throws IOException{
		this.localName = localName;
		this.remoteName = remoteName;
		this.url = "";
		streamConnection = con;
		openStreams();
	}
	
	/**
	 * method for preparing streams to be ready to read and write
	 * @throws IOException
	 */
	private void openStreams() throws IOException{
		inputStream=streamConnection.openInputStream();
		outputStream=streamConnection.openOutputStream();
	}
	
	/**
	 * creates a stream connection from a given url and open streams for read and write
	 * @throws IOException
	 */
	private void connect() throws IOException{
		streamConnection = (StreamConnection) Connector.open( url );
		openStreams();
	}
	
	/**
	 * closes connections and streams
	 * @throws IOException
	 */
	synchronized public void close() throws IOException{
		try{
			outputStream.close();
			inputStream.close();
			if(streamConnection!=null){
				streamConnection.close();
				streamConnection = null;
			}
		}
		catch(IOException e){}
	}
	
	/**
	 * writes int portion of data to stream
	 * @param c int value to be send
	 * @throws IOException
	 */
	public void writeInt(int c) throws IOException{
		outputStream.write(c);
		outputStream.flush();
	}
	
	/**
	 * reads single int value from the stream
	 * @return read int
	 * @throws IOException
	 */
	public int readInt() throws IOException{
		return inputStream.read();
	}
	
	/**
	 * writes whole String to bluetooth stream
	 * @param str string to be sent
	 * @throws IOException
	 */
	public void writeString(String str) throws IOException{
		//send string size
		writeInt(str.length()); //with flush
		for(int i=0;i<str.length();++i){
			outputStream.write((int)str.charAt(i)); //no flush
		}
		outputStream.flush(); //now send it!
	}
	
	/**
	 * reads whole String from bluetooth input stream 
	 * @return read String
	 * @throws IOException
	 */
	public String readString() throws IOException{
		int size=inputStream.read();
		char[] buf = new char[size];
		for(int i=0;i<size;++i){
			buf[i]=(char)inputStream.read();
		}
		return new String(buf);
	}
	
	/**
	 * @return remoteName
	 */
	public String getRemoteName() {
		return remoteName;
	}
	/**
	 * @param remoteName
	 */
	public void setRemoteName(String remoteName) {
		this.remoteName = remoteName;
	}
	/**
	 * @return localName
	 */
	public String getLocalName() {
		return localName;
	}
	/**
	 * @return if stream connection is closed
	 */
	public boolean isClosed(){
		return streamConnection == null;
	}
}
